using System.Collections.Immutable;
using System.Text;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;

namespace UnmanagedClass.Generator
{
    [Generator(LanguageNames.CSharp)]
    public class ChildClassGenerator : IIncrementalGenerator
    {
        public void Initialize(IncrementalGeneratorInitializationContext context)
        {
            // 筛选带有 UCInherit 特性的结构体
            var candidates = context.SyntaxProvider.CreateSyntaxProvider(
                    predicate: IsCandidate,
                    transform: TransformToSymbol)
                .Where(s => s != null);

            var combo = context.CompilationProvider.Combine(candidates.Collect());
            context.RegisterSourceOutput(combo, Execute);
        }

        private static bool IsCandidate(SyntaxNode node, CancellationToken ct)
        {
            return node is StructDeclarationSyntax { AttributeLists.Count: > 0 };
        }

        private static ISymbol TransformToSymbol(GeneratorSyntaxContext ctx, CancellationToken ct)
        {
            var structDecl = (StructDeclarationSyntax)ctx.Node;
            foreach (var al in structDecl.AttributeLists)
            {
                foreach (var attr in al.Attributes)
                {
                    var ctor = ctx.SemanticModel.GetSymbolInfo(attr).Symbol as IMethodSymbol;
                    if (ctor == null) continue;
                    var at = ctor.ContainingType;
                    if (at != null && (at.Name == "UCInherit" || at.Name == "UCInheritAttribute"))
                    {
                        return ctx.SemanticModel.GetDeclaredSymbol(structDecl);
                    }
                }
            }

            return null;
        }

        private void Execute(SourceProductionContext spc, (Compilation Left, ImmutableArray<ISymbol> Right) pair)
        {
            var compilation = pair.Left;
            var symbols = pair.Right;
            if (symbols == null) return;

            foreach (var sym in symbols)
            {
                if (sym is not INamedTypeSymbol template) continue;

                // 获取基类型
                var inheritAttr = template.GetAttributes()
                    .FirstOrDefault(a => a.AttributeClass.Name is "UCInherit" or "UCInheritAttribute");

                if (inheritAttr == null) continue;

                var baseType = inheritAttr.ConstructorArguments[0].Value as INamedTypeSymbol;
                if (baseType == null) continue;

                // 生成代码
                var source = GenerateChildSource(template, baseType);
                var fileName = $"{template.ContainingNamespace.Name}_{template.Name}.gen.cs";
                spc.AddSource(fileName, SourceText.From(source, Encoding.UTF8));
            }
        }

        private string GenerateChildSource(INamedTypeSymbol childSymbol, INamedTypeSymbol baseType)
        {
            var sb = new StringBuilder();
            sb.AppendLine("// <auto-generated/>");
            sb.AppendLine("#pragma warning disable 1591");
            sb.AppendLine("using System;");
            sb.AppendLine("using System.Runtime.InteropServices;");
            sb.AppendLine("using DA.AnimGraph.Share;");
            sb.AppendLine("using Battle.Math;");
            sb.AppendLine();

            var namespaceName = childSymbol.ContainingNamespace.ToDisplayString();
            if (!childSymbol.ContainingNamespace.IsGlobalNamespace)
            {
                sb.AppendLine($"namespace {namespaceName}");
                sb.AppendLine("{");
            }

            // 生成 Obsolete 结构体
            sb.AppendLine($"    [Obsolete(\"请使用 {childSymbol.Name}UC 替代\", error: true)]");
            sb.AppendLine($"    public unsafe partial struct {childSymbol.Name}");
            sb.AppendLine("    {");
            // 为每个UCOverride方法生成非静态的空实现（去掉第一个void* self参数）
            foreach (var member in childSymbol.GetMembers())
            {
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCOverrideAttribute"))
                {
                    // 跳过第一个void* self参数
                    var parameters = method.Parameters.Skip(1);
                    var parameterList = string.Join(", ", parameters.Select(p => $"{p.Type.ToDisplayString()} {p.Name}"));
                    // 生成非静态方法（去掉static关键字）
                    sb.AppendLine($"        public {method.ReturnType.ToDisplayString()} {method.Name}({parameterList}) => throw new Exception();");
                }
            }

            // 添加DisposeParent空方法
            sb.AppendLine("        static void DisposeParent(void* self){}");
            sb.AppendLine("    }");
            sb.AppendLine();

            // 生成 UC 结构体
            sb.AppendLine($"    public unsafe struct {childSymbol.Name}UC");
            sb.AppendLine("    {");
            // 修正：直接使用基类型的 UC 名称
            string baseTypeName = baseType.Name;
            sb.AppendLine($"        public {baseTypeName} __base__;");
            sb.AppendLine();

            // 修正：虚函数表类型名称应该是基类型名称 + "VT"
            string vtTypeName = baseType.Name + "VT";
            sb.AppendLine($"        public {vtTypeName}* __vt__");
            sb.AppendLine("        {");
            sb.AppendLine($"            get => __base__.__vt__;");
            sb.AppendLine($"            private set {{ __base__.__vt__ = value; }}");
            sb.AppendLine("        }");
            sb.AppendLine();

            // 复制所有非静态字段
            foreach (var member in childSymbol.GetMembers())
            {
                if (member is IFieldSymbol field && !field.IsStatic)
                {
                    sb.AppendLine($"        public {field.Type.ToDisplayString()} {field.Name};");
                }
            }

            sb.AppendLine();

            // 添加 New 方法
            sb.AppendLine($"        public static {childSymbol.Name}UC* New(ref BlockBuffer buffer)");
            sb.AppendLine("        {");
            sb.AppendLine($"            var obj = buffer.Malloc<{childSymbol.Name}UC>();");
            sb.AppendLine($"            {childSymbol.Name}UC.__ctor__(ref *obj, ref buffer);");
            sb.AppendLine($"            return obj;");
            sb.AppendLine("        }");
            sb.AppendLine();

            // 添加构造函数
            sb.AppendLine($"        public static void __ctor__(ref {childSymbol.Name}UC obj, ref BlockBuffer buffer)");
            sb.AppendLine("        {");
            sb.AppendLine($"            var vt = buffer.Malloc<{vtTypeName}>();");

            // 为每个 UCOverride 方法设置函数指针
            foreach (var member in childSymbol.GetMembers())
            {
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCOverrideAttribute"))
                {
                    sb.AppendLine($"            vt->{method.Name} = &{method.Name}_Implement;");
                }
            }

            sb.AppendLine($"            obj.__vt__ = vt;");
            sb.AppendLine("        }");
            sb.AppendLine();

            // 添加虚函数调用方法
            foreach (var member in childSymbol.GetMembers())
            {
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCOverrideAttribute"))
                {
                    var parameters = method.Parameters.Skip(1); // 跳过第一个 void* self 参数
                    var parameterList = parameters.Any() ? string.Join(", ", parameters.Select(p => $"{p.Type.ToDisplayString()} {p.Name}")) : "";
                    var argumentList = parameters.Any() ? string.Join(", ", parameters.Select(p => p.Name)) : "";

                    // 确定是否需要 return 语句
                    bool hasReturnValue = method.ReturnType.SpecialType != SpecialType.System_Void;
                    string returnKeyword = hasReturnValue ? "return " : "";

                    sb.AppendLine($"        public {method.ReturnType.ToDisplayString()} {method.Name}({parameterList})");
                    sb.AppendLine("        {");
                    sb.AppendLine($"            fixed ({childSymbol.Name}UC* selfPtr = &this)");
                    sb.AppendLine("            {");

                    if (parameters.Any())
                    {
                        sb.AppendLine($"                {returnKeyword}selfPtr->__vt__->{method.Name}(selfPtr, {argumentList});");
                    }
                    else
                    {
                        sb.AppendLine($"                {returnKeyword}selfPtr->__vt__->{method.Name}(selfPtr);");
                    }

                    sb.AppendLine("            }");
                    sb.AppendLine("        }");
                    sb.AppendLine();
                }
            }

            // 复制所有非UCOverride的成员（包括静态方法、静态字段等）
            foreach (var member in childSymbol.GetMembers())
            {
                // 跳过特殊处理的成员
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCOverrideAttribute"))
                {
                    continue;
                }

                // 跳过已经处理的字段
                if (member is IFieldSymbol field && !field.IsStatic)
                {
                    continue;
                }

                // 跳过已经处理的基类字段
                if (member.Name == "__base__" || member.Name == "__vt__")
                {
                    continue;
                }

                // 复制其他所有成员
                var syntaxRef = member.DeclaringSyntaxReferences.FirstOrDefault();
                if (syntaxRef != null)
                {
                    var syntax = syntaxRef.GetSyntax();
                    if (syntax != null)
                    {
                        // 跳过属性的下层节点
                        if (syntax is AccessorDeclarationSyntax || syntax is ArrowExpressionClauseSyntax) continue;
                        // 复制成员
                        var memberText = syntax.ToFullString();
                        sb.AppendLine(memberText);
                    }
                }
            }

            // 添加实现方法 - 修正：直接复制源代码，不进行类型替换
            foreach (var member in childSymbol.GetMembers())
            {
                if (member is IMethodSymbol method && method.IsStatic &&
                    method.GetAttributes().Any(a => a.AttributeClass.Name == "UCOverrideAttribute"))
                {
                    // 获取方法的完整实现
                    var syntaxRef = method.DeclaringSyntaxReferences.FirstOrDefault();
                    if (syntaxRef != null)
                    {
                        var methodSyntax = syntaxRef.GetSyntax() as MethodDeclarationSyntax;
                        if (methodSyntax != null)
                        {
                            var parameters = method.Parameters.Skip(1); // 跳过第一个 void* self 参数
                            var parameterList = parameters.Any() ? string.Join(", ", parameters.Select(p => $"{p.Type.ToDisplayString()} {p.Name}")) : "";

                            sb.AppendLine($"        private static {method.ReturnType.ToDisplayString()} {method.Name}_Implement(void* self{(parameters.Any() ? ", " + parameterList : "")})");
                            sb.AppendLine("        {");

                            // 提取方法体，直接复制，不进行类型替换
                            if (methodSyntax.Body != null)
                            {
                                // 获取方法体的完整文本
                                var bodyText = methodSyntax.Body.ToFullString();

                                // 移除大括号
                                bodyText = bodyText.Trim();
                                if (bodyText.StartsWith("{")) bodyText = bodyText.Substring(1);
                                if (bodyText.EndsWith("}")) bodyText = bodyText.Substring(0, bodyText.Length - 1);

                                // 按行分割并添加适当的缩进
                                var lines = bodyText.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
                                foreach (var line in lines)
                                {
                                    if (!string.IsNullOrWhiteSpace(line))
                                    {
                                        sb.AppendLine($"            {line.Trim()}");
                                    }
                                }
                            }

                            sb.AppendLine("        }");
                            sb.AppendLine();
                        }
                    }
                }
            }

            // 添加 DisposeParent 方法
            sb.AppendLine($"        static void DisposeParent(void* self)");
            sb.AppendLine("        {");
            sb.AppendLine($"            var basePtr = ({baseType.Name}*)self;");
            sb.AppendLine("            basePtr->Dispose();");
            sb.AppendLine("        }");

            sb.AppendLine("    }");

            if (!childSymbol.ContainingNamespace.IsGlobalNamespace)
            {
                sb.AppendLine("}");
            }

            return sb.ToString();
        }
    }
}